/**
 * ts泛型工具 内置类型定义
 */

// Partial的作用是将传入的属性变成可选项，原理就是使用keyof拿到所有的属性名，然后在使用in遍历，T[P]拿到相应的值
type Partial<T> = { [P in keyof T]?: T[P] }

// Required的作用是将传入的属性变为必选项，原理就是使用-?，将可选项的?去掉。与之对应的还有个+?
type Required<T> = { [P in keyof T]-?: T[P] }

// Readonly的作用是将传入的属性变为只读选项
type Readonly<T> = { readonly [P in keyof T]: T[P] }

// Pick的作用是从T中取出一系列K的属性
type Pick<T, K extends keyof T> = { [P in K]: T[P] }

// Record的作用是将K中所有属性的值转化成T类型
type Record<K extends keyof any, T> = { [P in K]: T }

// Exclude的作用是从T中找出U中没有的元素
type Exclude<T, U> = T extends U ? never : T

// Extract的作用是从T中找出U中所有的元素
type Extract<T, U> = T extends U ? T : never

// ReturnType的作用是用来得到一个函数的返回值类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any

// ThisType用于指定上下文对象类型
interface ThisType<T> {}

// InstanceType的作用是获取一个类的实例类型，可以用获取到的实例类型来约束一个变量的赋值必须和类的成员类型完全一样才可以
type InstanceType<T extends new (...args: any[]) => any> = T extends new (
  ...args: any[]
) => infer R
  ? R
  : any

// NonNullable的作用是去除 T 中包含的null或者undefined
type NonNullable<T> = T extends null | undefined ? never : T

// Parameters的作用是用来获取一个函数的参数类型，而且返回的是只能包含一组类型的数组
type Parameters<T extends (...args: any[]) => any> = T extends (
  ...args: infer P
) => any
  ? P
  : never

// ConstructorParameters的作用是用来获取一个类的构造函数参数类型，并以数组的形式返回
type ConstructorParameters<T extends new (...args: any[]) => any> =
  T extends new (...args: infer P) => any ? P : never

/**
 * ts泛型工具 非内置类型定义
 */

// Omit的作用是忽略对象的某些属性功能
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>

// DeepReadonly用来深度遍历 T，并将其所有属性变成只读类型
type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> }

// ConvertNumberToString用来将number转换为string类型
type ConvertNumberToString<T> = {
  [K in keyof T]: T[K] extends string ? string : T[K]
}

// ValueOf与keyof相对应。取出指定类型的所有 value
type ValueOf<T> = T[keyof T]

// 用来将所有属性的readonly移除
type Mutable<T> = { -readonly [P in keyof T]: T[P] }
